#include "watch.h"
#include "global_variables.h"

ostream &operator<<(ostream &os, watch &w) {
  string temp;
  os << w.get_elapsed_time(temp);
  return os;
} // operator<<

void watch::start() {
  c = clock();
  is_running = true;
  elapsed_time = 0ULL;
} // watch::start

void watch::stop() {
  if (is_running == true) {
    c = clock() - c;

    elapsed_time = (unsigned long long) ((double) c / CLOCKS_PER_SEC * 1000);
    is_running = false;
  } // if
} // watch::stop

unsigned long long watch::get_elapsed_milliseconds() {
  stop();
  return elapsed_time;
} // watch::get_elapsed_milliseconds

unsigned long long watch::get_elapsed_seconds() {
  stop();
  return elapsed_time / 1000;
} // watch::get_elapsed_seconds

unsigned long long watch::get_elapsed_minutes() {
  stop();
  return elapsed_time / 60000;
} // watch::get_elapsed_minutes

unsigned long long watch::get_elapsed_hours() {
  stop();
  return elapsed_time / 3600000;
} // watch::get_elapsed_hours

unsigned long long watch::get_elapsed_days() {
  stop();
  return elapsed_time / 86400000;
} // watch::get_elapsed_days

string &watch::get_elapsed_time(string &output) {
  stop();
  char buffer[16] = { "\0" };

  const unsigned short hours = (unsigned short) (elapsed_time / 3600000);
  const unsigned short minutes = (unsigned short) ((elapsed_time - (hours * 3600000)) / 60000);
  const unsigned short seconds = (unsigned short) ((elapsed_time - (hours * 3600000) - (minutes * 60000)) / 1000);
  const unsigned short milliseconds = (unsigned short) (elapsed_time % 1000);

  const int length = sprintf(buffer, "%u:%02u:%02u.%u", hours, minutes, seconds, milliseconds);
  output.assign(buffer, length);
  return output;
} // watch::get_elapsed_time

string &watch::get_current_time(string &output) const {
  output.clear();

  time_t now;
  const int buffer_size = 32;
  char buffer[buffer_size + 1] = { "\0" };

  time(&now);
  if (now == -1)
    return output;

  struct tm *ptr = localtime(&now);
  if (ptr == 0)
    return output;

  const size_t length = strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", ptr);
  output.assign(buffer, length);
  return output;
} // watch::get_current_time

watch::watch(bool auto_start) : elapsed_time(0), c(0), is_running(false) {
  if (auto_start == true)
    start();
} // watch::watch

watch::~watch() {
  // nothing to do
} // watch::~watch
